package matheus.tp01cg.objetosdedesenho;


/**
 * Classe base para Reta. Armazena os pontos inicial e final alem da cor da reta
 * 
 * TODO: Ver o campo nula para clone das retas
 * 
 * @author matheus
 * 
 */
public abstract class Reta extends ObjetoDeDesenho {
	private Coords pontoInicial;
	private Coords pontoFinal;
	public boolean nula = false; // para utilizacao dos algoritmos de recorte

	public Coords getPontoInicial() {
		return pontoInicial;
	}

	public void setPontoInicial(Coords pontoInicial) {
		this.pontoInicial = pontoInicial;
	}

	public Coords getPontoFinal() {
		return pontoFinal;
	}

	public void setPontoFinal(Coords pontoFinal) {
		this.pontoFinal = pontoFinal;
	}

	public Reta(Coords pontoInicial, Coords pontoFinal, int cor) {
		setPontoInicial(pontoInicial);
		setPontoFinal(pontoFinal);
		setCorContorno(cor);
	}

	@Override
	public void rotaciona(Coords centro, double angulo) {
		pontoInicial.rotaciona(centro, angulo);
		pontoFinal.rotaciona(centro, angulo);
	}

	@Override
	public void translada(int x, int y) {
		pontoInicial.translada(x, y);
		pontoFinal.translada(x, y);
	}

	@Override
	public void escala(Coords ref, double x, double y) {
		pontoInicial.escala(ref, x, y);
		pontoFinal.escala(ref, x, y);
	}

	@Override
	public int getMinX() {
		return (pontoInicial.x < pontoFinal.x) ? pontoInicial.x : pontoFinal.x;
	}

	@Override
	public int getMinY() {
		return (pontoInicial.y < pontoFinal.y) ? pontoInicial.y : pontoFinal.y;
	}

	@Override
	public int getMaxX() {
		return (pontoInicial.x > pontoFinal.x) ? pontoInicial.x : pontoFinal.x;
	}

	@Override
	public int getMaxY() {
		return (pontoInicial.y > pontoFinal.y) ? pontoInicial.y : pontoFinal.y;
	}

	public static class Equacao {
		double a, b;

		protected Equacao(double a, double b) {
			this.a = a;
			this.b = b;
		}

		public static Equacao criar(Coords pontoA, Coords pontoB) {
			double a, b;
			int x1, y1, x2, y2;
			x1 = pontoA.x;
			y1 = pontoA.y;
			x2 = pontoB.x;
			y2 = pontoB.y;
			a = (double) (y2 - y1) / (double) (x2 - x1);
			b = y1 - ((double) (y2 - y1) / (double) (x2 - x1)) * (double) x1;
			return new Equacao(a, b);
		}

		public double y(int x) {
			return a * (double) x + b;
		}

		public double x(int y) {
			return ((double) y - b) / a;
		}
	}

	public static boolean intercepta(Coords retaPontoA, Coords retaPontoB,
			Coords ponto, int raio) {
		// min < x < max
		if (!((Math.min(retaPontoA.x, retaPontoB.x) - raio) < ponto.x && ponto.x < (Math
				.max(retaPontoA.x, retaPontoB.x) + raio))) {
			return false;
		}
		// min < y < max
		if (!((Math.min(retaPontoA.y, retaPontoB.y) - raio) < ponto.y && ponto.y < (Math
				.max(retaPontoA.y, retaPontoB.y) + raio))) {
			return false;
		}

		Equacao reta = Equacao.criar(retaPontoA, retaPontoB);
		int xMin = (ponto.x - raio);
		int xMax = (ponto.x + raio);
		int yMin = (ponto.y - raio);
		int yMax = (ponto.y + raio);
		double y = reta.y(ponto.x);
		double x = reta.x(ponto.y);

		if (Double.isNaN(x) || Double.isInfinite(x)) { // reta totalmente vertical
			x = retaPontoA.x;
		}
		return (yMin <= y && y <= yMax) || (xMin <= x && x <= xMax);
	}

	@Override
	public boolean intercepta(Coords ponto, int raio) {
		return intercepta(pontoInicial, pontoFinal, ponto, raio);
	}
}
